package com.firexxx.vp.adapter.controller;

import com.firexxx.common.errors.BaseErrors;
import com.firexxx.vp.application.StbCommandService;
import com.firexxx.vp.application.dto.AudioDto;
import com.firexxx.vp.application.dto.StbDto;
import com.firexxx.vp.application.dto.VPMatchDto;
import com.firexxx.vp.domain.audio.AudioType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
 * @description: TODO
 * @throws:
 * @author: zhuangzhang2
 * @date: 2019/12/23 11:41
 */
@RestController
@Slf4j
@RequestMapping(value = "/voiceprint")
@Validated
public class VoicePrintController implements InitializingBean {

    @Value("${post.chunkedCacheSize}")
    private int chunkedCacheSize;

    @Value("${post.chunkedWaitTime}")
    private long chunkedWaitTime;

    @Value("${audio.matchMinVoiceLength}")
    private int matchMinVoiceLength;

    @Autowired
    private StbCommandService stbCommandService;

//    @GetMapping(value = "/test")
//    public void test() {
//        StbEntity stbEntity = stbCommandService.test();
//
//        stbCommandService.test1(stbEntity);
//    }

    @PostMapping(value = "/match")
    public VPMatchDto match(@NotBlank @RequestHeader("sid") String audioId,
                            @NotBlank @RequestHeader("channelId") String channelId,
                            @RequestHeader("stbId") String stbId,
                            @RequestHeader("mac") String mac,
                            HttpServletRequest request, HttpServletResponse response) throws Throwable {
        BaseErrors.INVALID_PARAM.ifThrow(
                StringUtils.isBlank(stbId) && StringUtils.isBlank(mac),
                "输入参数无效");

        //接收语音流，并以chunck模式转发语音
        long startTime = System.currentTimeMillis();
        InputStream inputStream = request.getInputStream();
        byte[] buffer = new byte[chunkedCacheSize];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int length = -1;
        int offset = 0;
        while ((length = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, offset, length);
            offset += length;

            Thread.sleep(chunkedWaitTime);
        }
        byte[] content = byteArrayOutputStream.toByteArray();
        log.info("chunk音频接收耗时={}", System.currentTimeMillis() - startTime);

        StbDto stbDto = new StbDto(audioId, channelId, stbId, mac);
        AudioDto audioDto = null;
        BaseErrors.INVALID_PARAM.ifThrow(
                content.length < matchMinVoiceLength,
                "pcm音频长度太短");
        audioDto = new AudioDto(audioId, audioId, content, AudioType.PCM);

        return stbCommandService.match(stbDto, audioDto);
    }

    @PostMapping(value = "/postMatch")
    public VPMatchDto postMatch(@NotBlank @RequestHeader("sid") String audioId,
                                @NotBlank @RequestHeader("channelId") String channelId,
                                @RequestHeader("stbId") String stbId,
                                @RequestHeader("mac") String mac,
                                @Size(min = 1, max = 1) @RequestParam("files") MultipartFile[] files,
                                HttpServletRequest request, HttpServletResponse response) throws Throwable {
        BaseErrors.INVALID_PARAM.ifThrow(
                StringUtils.isBlank(stbId) && StringUtils.isBlank(mac),
                "输入参数无效");

        byte[] content = files[0].getBytes();

        StbDto stbDto = new StbDto(audioId, channelId, stbId, mac);
        AudioDto audioDto = null;
        BaseErrors.INVALID_PARAM.ifThrow(
                content.length < matchMinVoiceLength,
                "pcm音频长度太短");

        audioDto = new AudioDto(audioId, audioId, content, AudioType.PCM);

        return stbCommandService.match(stbDto, audioDto);
    }

    @GetMapping(value = "/register")
    public void register(@NotBlank @RequestHeader("sid") String audioId,
                         @NotBlank @RequestHeader("channelId") String channelId,
                         @RequestHeader("stbId") String stbId,
                         @RequestHeader("mac") String mac) throws Throwable {
        BaseErrors.INVALID_PARAM.ifThrow(
                StringUtils.isBlank(stbId) && StringUtils.isBlank(mac),
                "输入参数无效");

        StbDto stbDto = new StbDto(audioId, channelId, stbId, mac);
        stbCommandService.registerStb(stbDto);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        if (System.getProperty("os.name").toLowerCase().indexOf("windows")>=0) {
            return;
        }
    }
}